package lab;

import process.Dispatcher;
import process.QueueForTransactions;
import process.Store;
import qusystem.MultiActor;
import stat.DiscretHisto;
import stat.Histo;
import widgets.experiments.IExperimentable;
import widgets.trans.ITransProcesable;
import widgets.trans.TransProcessStore;

public class Model implements IExperimentable, ITransProcesable {
	
	private Dispatcher dispatcher;
	private mainGUI gui;

	public Kran getKran() {
		if (kran==null){
			kran = new Kran("hranilische", gui, this);
		}
		return kran;
	}

	public Gruzovik getGr() {
		if (gr==null){
			gr = new Gruzovik("gruzovic", gui, this);
		}
		return gr;
	}

	private Kran kran;
	private Gruzovik gr;
	private Ship sh;
	
	public Ship getSh() {
		if (sh==null){
			sh= new Ship("konteyneru",gui,this);
		}
		return sh;
	}

	private MultiActor stadoGruzovikov;
	private Store qContainer;
	private QueueForTransactions qGruzovik;
	private QueueForTransactions qGruzovikOnRoad;
	private TransProcessStore qSquare;
	private Histo histoSq;
	
	public Histo getHistoSq(){
		if (histoSq==null){
			histoSq = new Histo();
		}
		return histoSq;
		
	}
	

	public TransProcessStore getqSquare() {
		if (qSquare == null) {
			qSquare = new TransProcessStore();
			qSquare.setNameForProtocol("ploschadka");
			qSquare.setDispatcher(dispatcher);
			qSquare.setHisto(getHistoSq());
			qSquare.init();
		}
		return qSquare;
	}

	public QueueForTransactions getqGruzovikOnRoad() {
		if (qGruzovikOnRoad==null){
			qGruzovikOnRoad = new QueueForTransactions();
			qGruzovikOnRoad.setNameForProtocol("gryzovic v doroge");
			qGruzovikOnRoad.setDispatcher(dispatcher);
			qGruzovikOnRoad.init();
		}
		return qGruzovikOnRoad;
	}

	private DiscretHisto qGruzovikToKran;
	private double lastSumTime;
	private int sum;
	private int accumTime;
	
	public Model(Dispatcher d, mainGUI g){
		if (d==null || g==null) {
			System.out.println("FAIL");
			System.exit(0);
		}
		this.dispatcher=d;
		this.gui=g;
		componentsToStartList();
		
	}

	private void componentsToStartList() {
		// TODO Auto-generated method stub
		//dispatcher.addStartingActor(getCont());
		dispatcher.addStartingActor(getSh());
		dispatcher.addStartingActor(getKran());
		dispatcher.addStartingActor(getStadoGruzovikov());
	}

	public Store getqContainer() {
		if (qContainer==null) {
			qContainer = new Store();
			qContainer.setNameForProtocol("konteyneru do krana");
			qContainer.setDispatcher(dispatcher);
			
		}
		return qContainer;
	}
	
	public QueueForTransactions getqGruzovik() {
		if (qGruzovik==null) {
			qGruzovik = new QueueForTransactions();
			qGruzovik.setNameForProtocol("gryzoviki k krany");
			qGruzovik.setDispatcher(dispatcher);
			qGruzovik.setDiscretHisto(getqGruzovikToKran());
			qGruzovik.init();
		}
		return qGruzovik;
	}
	

	public DiscretHisto getqGruzovikToKran() {
		if (qGruzovikToKran==null) {
			qGruzovikToKran = new DiscretHisto();
			qGruzovikToKran.init();
			
		}
		return qGruzovikToKran;
	}

	public MultiActor getStadoGruzovikov() {
		if (stadoGruzovikov ==null) {
			stadoGruzovikov = new MultiActor();
			stadoGruzovikov.setNameForProtocol("gryzoviki v pyti");
			stadoGruzovikov.setOriginal(getGr());
			stadoGruzovikov.setNumberOfClones(gui.getCountOfGruz().getInt());
		}
		return stadoGruzovikov;
	}
	
	public void initForTest(){
		getqContainer().setPainter(gui.getContainer().getPainter());
		getqSquare().setPainter(gui.getSquareDiagram().getPainter());
		getqGruzovik().setPainter(gui.getGruzovikToKran().getPainter());
		getqGruzovikOnRoad().setPainter(gui.getGruzovikOnRoad().getPainter());
	}
	
	public void initForStat(){
		dispatcher.setProtocolFileName("Console");
	}

	@Override
	public void initForExperiment(double factor) {
		// TODO Auto-generated method stub
		this.dispatcher.setProtocolFileName("");
		this.stadoGruzovikov.setNumberOfClones((int)factor);
	}

	@Override
	public double getResultOfExperiment() {
		// TODO Auto-generated method stub
		if (this.gui.getRadioT().isSelected())
		      return this.qGruzovikToKran.getAverage();
		    return getHistoSq().average();
	}

	@Override
	public void initForTrans(double timeModel) {
		   gui.getTimeWork().setText(String.valueOf(timeModel));
		   int modelID = hashCode();
		   dispatcher.setProtocolFileName(null);
		   
		   getqGruzovik().setNameForProtocol("zagruzhenost' ploschadki " + modelID);
		   getqGruzovik().init();
		   getqGruzovik().setPainter(null);
		   getStadoGruzovikov().setNumberOfClones(gui.getSizeOfSquare().getInt());
	}

	@Override
	public void resetTransAccum() {
		  lastSumTime = dispatcher.getCurrentTime();
		   sum = 0;
		   accumTime = 0;
	}

	@Override
	public double getTransResult() {
		double dt = dispatcher.getCurrentTime() - lastSumTime;
		   lastSumTime = dispatcher.getCurrentTime();
		   sum += dt * getqSquare().getSize(); 
		   accumTime += dt;
		   return sum / accumTime;
	}

	
	public void initForExperiment(double arg0, double arg1) {
		// TODO Auto-generated method stub
		
	}

}
